package com.example.administrator.renrensideslip;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.widget.LinearLayout;

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";

    /** Menu视图 **/
    private View viewMenu;
    /** Menu的布局参数，用于修改Menu位置 **/
    private LinearLayout.LayoutParams menuLp;
    /** 主View **/
    private View viewContent;
    /** menu的宽度 **/
    private int menuWidth;
    /** 可以滑动到左边的距离，为-menu的宽度 ，当leftMargin到达该值时，不能再减少了**/
    private int leftEdge;
    /** 可以滑动到右边的距离，为0，当leftMargin到达该值时，不能再增加了 **/
    private int rightEdge = 0;
    /** 手指按下时候的横坐标 ***/
    private float xDown;
    /** 手指移动时候的横坐标 **/
    private float xMove;
    /** 手指抬起时候的横坐标 **/
    private float xUp;
    /** Menu是否正在显示 **/
    private boolean isMenuVisiable;
    /** 滚动显示和隐藏Menu时，手指滑动需要达到的速度 **/
    private static final int SANP_VELOCITY = 200;
    /** 屏幕宽度 **/
    private int screenWidth;
    /** 用于计算手指滑动的速度 **/
    private VelocityTracker mVelocityTracker;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        findViews();
    }

    private void init() {
        int width = getWindowManager().getDefaultDisplay().getWidth();
        Log.e(TAG, "findViews: width:" + width );
        screenWidth = getWindowManager().getDefaultDisplay().getWidth();
        menuWidth = (int) (screenWidth * 0.8f);
        leftEdge =  -menuWidth;
        Log.e(TAG, "findViews: menuWidth:" + menuWidth );
    }

    private void findViews() {
        viewMenu = (View) findViewById(R.id.view_menu);
        viewContent = (View) findViewById(R.id.view_content);

        menuLp = (LinearLayout.LayoutParams) viewMenu.getLayoutParams();
        menuLp.width = menuWidth;
        //初始化menu位置，让其隐藏
        menuLp.leftMargin = leftEdge;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        createVelocityTracker(event);
        Log.e(TAG, "onTouchEvent: ");
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //按下时，记录手指按下的横坐标
                xDown = event.getRawX();
                break;
            case MotionEvent.ACTION_MOVE:
                //移动时
                xMove = event.getRawX();
                int moveDistance = (int) (xMove - xDown);
                Log.e(TAG, "ACTION_MOVE moveDistance: moveDistance):" + moveDistance );
                if (isMenuVisiable) {
                    menuLp.leftMargin  = moveDistance;
                } else {
                    menuLp.leftMargin = leftEdge + moveDistance;
                }
                if (menuLp.leftMargin < leftEdge) {
                    menuLp.leftMargin = leftEdge;
                } else if (menuLp.leftMargin > rightEdge){
                    menuLp.leftMargin = rightEdge;
                }
                viewMenu.setLayoutParams(menuLp);
                break;
            case MotionEvent.ACTION_UP:
                Log.e(TAG, "ACTION_UP" );
                xUp = event.getRawX();
                if (wantToShowMenu() || wantToShowContent()) { //去除，显示了menu时，继续往右滑；显示了content时，继续往左滑的情况
                    if (shouldScrollToMenu()) {
                        Log.e(TAG, "onTouchEvent: shouldScrollToMenu" );
                        scrollToMenu();
                    } else if (shouldScrollToCeontent()){
                        Log.e(TAG, "onTouchEvent: shouldScrollToCeontent" );
                        scrollToContent();
                    }
                }
                recycleVelocityTracker();
                break;
        }
        //自己处理了事件，不向外传递
        return true;
    }

    /**
     * 回收VelocityTracker对象
     */
    private void recycleVelocityTracker() {
        mVelocityTracker.recycle();
        mVelocityTracker = null;
    }

    /**
     * 将屏幕滚动到menu界面，滚动速度为30
     */
    private void scrollToMenu() {
        new ScrollTask().execute(30);
    }

    /**
     *  将屏幕滚动到content界面，滚动速度为-30
     */
    private void scrollToContent() {
        new ScrollTask().execute(-30);
    }

     /**
     * 创建VelocityTracker对象，并将触摸content界面的滑动事件，加入到VeloctiyTracker中
     * @param event
     */
    private void createVelocityTracker(MotionEvent event) {
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);
    }

    /**
     * 是否是想显示菜单，只有当抬起时，横坐标大于按下时的横坐标，并且menu没显示时，才认为，需要显示menu
     * @return
     */
    private boolean wantToShowMenu() {
        return (xUp - xDown > 0) && !isMenuVisiable;
    }

    /**
     * 判断当前手势，是不是想显示content，如果手指移动的距离是负数，并且当前menu是可见的，则认为当前手势是要显示content
     * @return
     */
    private boolean wantToShowContent() {
        return (xUp - xDown < 0) && isMenuVisiable;
    }

    /**
     * 判断是否应该将menu展示出来，如果手指移动距离距离大于屏幕的1/2. 或者手指移动速度大于sanp_velocity
     * 就应该滚动将menu展示出来
     * @return
     */
    private boolean shouldScrollToMenu() {
        if ((!isMenuVisiable && getScrollVelocity() > SANP_VELOCITY)  || (xUp - xDown) > screenWidth / 2 ) {
            return true;
        }
        //当显示menu时，当回滑不到一半时，则继续回到显示menu处
        if (isMenuVisiable && (xDown - xUp + screenWidth * 0.2) <= screenWidth / 2 && getScrollVelocity() < SANP_VELOCITY) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否应该滚动将Content展示出来，如果手指移动距离加上menuPadding大于屏幕的1/2
     * 或者手指移动速度大于Snap_velocity，就应该滚动将content展示出来
     * @return
     */
    private boolean shouldScrollToCeontent() {
        if ((isMenuVisiable && getScrollVelocity() > SANP_VELOCITY)  || (xDown - xUp + screenWidth * 0.2) > screenWidth / 2) {
            return true;
        }
        //当不显示menu时，拉出menu不到一半时，则继续显示content
        if (!isMenuVisiable && (xUp - xDown) <= screenWidth / 2 && getScrollVelocity() < SANP_VELOCITY) {
            return true;
        }
        return false;
    }

    /**
     * 获取手指在Content界面滑动的速度
     * @return 滑动速度，以每秒移动了多少个像素值为单位
     */
    private int getScrollVelocity() {
        mVelocityTracker.computeCurrentVelocity(1000);
        int velocity = (int) mVelocityTracker.getXVelocity();
        Log.e(TAG, "getScrollVelocity: velocity: " + velocity);
        return Math.abs(velocity);
    }

    /**
     * 滚动的任务
     */
    class ScrollTask extends AsyncTask<Integer, Integer, Integer> {

        @Override
        protected Integer doInBackground(Integer... speed) {
            int leftMargin = menuLp.leftMargin;
            //根据传入的速度来滚动界面，当滚动到达左边或者右边界时，跳出循环
            while (true) {
                leftMargin = leftMargin + speed[0];
                if (leftMargin > rightEdge) {
                    leftMargin = rightEdge;
                    break;
                }
                if (leftMargin < leftEdge) {
                    leftMargin = leftEdge;
                    break;
                }

                publishProgress(leftMargin);
                //为了要有滚动效果产生，每次循环使线程休眠20毫秒，这样肉眼才能看到滚动动画
                sleep(20);
            }
            if (speed[0] > 0) {
                isMenuVisiable = true;
            } else {
                isMenuVisiable = false;
            }
            return leftMargin;
        }

        /**
         * 更新vieMenu的leftMargin
         * @param leftMargin
         */
        @Override
        protected void onProgressUpdate(Integer... leftMargin) {
            menuLp.leftMargin = leftMargin[0];
            viewMenu.setLayoutParams(menuLp);
        }

        @Override
        protected void onPostExecute(Integer  leftMargin) {
            menuLp.leftMargin = leftMargin;
            viewMenu.setLayoutParams(menuLp);
        }

    }

    /**
     * 使当前线程睡眠指定的毫秒数
     * @param millis
     */
    private void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
